package home.google.apps.client;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class ContactPhoneBook implements EntryPoint {

	private VerticalPanel verticalPanel = new VerticalPanel();
	private FlexTable flexTable = new FlexTable();
	private Button btnAddNewEntry = new Button("Add");
	private Button btnSearchEntry = new Button("Search Entry");
	private TextBox tSearch = new TextBox();
	private Label lblPhoneBook = new Label("Phone Book");
	private TextBox tPhoneNum = new TextBox();
	private TextBox tFullName = new TextBox();
	private ArrayList<Entry> entriesList = new ArrayList<Entry>();
	private final HorizontalPanel searchPanel = new HorizontalPanel();
	private final HorizontalPanel addPanel = new HorizontalPanel();
	private final Image image = new Image("images/lg_sfeir.jpg");
	private final HorizontalPanel headerPanel = new HorizontalPanel();
	private Label lblName = new Label("Full Name : ");
	private Label lblPhoneNum = new Label("Phone Number : ");
	private Label lblEnterTheFull = new Label("Enter the full name : ");

	private PersistentEntryServiceAsync service = GWT
			.create(PersistentEntryService.class);

	public void onModuleLoad() {

		RootPanel rootPanel = RootPanel.get("contactPhoneBook");
		rootPanel.setSize("600", "800");
		rootPanel.add(verticalPanel, 8, 8);
		verticalPanel.setSize("600px", "243px");
		lblName.addStyleName("addLabel");
		lblPhoneNum.addStyleName("addLabel");
		lblPhoneBook.addStyleName("title");
		addPanel.addStyleName("addAndSearchPanel");
		searchPanel.addStyleName("addAndSearchPanel");
		lblEnterTheFull.addStyleName("addLabel");

		headerPanel.add(image);
		headerPanel.add(lblPhoneBook);
		headerPanel.setCellVerticalAlignment(lblPhoneBook,
				HasVerticalAlignment.ALIGN_MIDDLE);
		headerPanel.setCellHorizontalAlignment(lblPhoneBook,
				HasHorizontalAlignment.ALIGN_CENTER);
		verticalPanel.add(headerPanel);

		verticalPanel.add(addPanel);
		addPanel.setSize("600px", "53px");
		addPanel.add(lblName);
		addPanel.setCellHorizontalAlignment(lblName, HasHorizontalAlignment.ALIGN_CENTER);
		lblName.setWidth("95px");
		addPanel.setCellVerticalAlignment(lblName, HasVerticalAlignment.ALIGN_MIDDLE);
		addPanel.add(tFullName);
		addPanel.setCellVerticalAlignment(tFullName, HasVerticalAlignment.ALIGN_MIDDLE);

		// Move cursor focus to the Name input box.
		tFullName.setFocus(true);

		addPanel.add(lblPhoneNum);
		addPanel.setCellVerticalAlignment(lblPhoneNum, HasVerticalAlignment.ALIGN_MIDDLE);
		addPanel.setCellHorizontalAlignment(lblPhoneNum, HasHorizontalAlignment.ALIGN_CENTER);
		lblPhoneNum.setWidth("103px");
		addPanel.add(tPhoneNum);
		addPanel.setCellVerticalAlignment(tPhoneNum, HasVerticalAlignment.ALIGN_MIDDLE);
		addPanel.add(btnAddNewEntry);
		addPanel.setCellVerticalAlignment(btnAddNewEntry, HasVerticalAlignment.ALIGN_MIDDLE);
		btnAddNewEntry.setWidth("41px");

		//Populate the FlexTable
		populateFlexTable();
		
		// Listen for mouse events on the Add button.
		btnAddNewEntry.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				addNewEntry();
			}
		});
		
		verticalPanel.add(searchPanel);
		searchPanel.setSize("600px", "53px");
		
		searchPanel.add(lblEnterTheFull);
		searchPanel.setCellHorizontalAlignment(lblEnterTheFull, HasHorizontalAlignment.ALIGN_CENTER);
		lblEnterTheFull.setWidth("212px");
		searchPanel.setCellVerticalAlignment(lblEnterTheFull, HasVerticalAlignment.ALIGN_MIDDLE);

		searchPanel.add(tSearch);
		searchPanel.setCellVerticalAlignment(tSearch, HasVerticalAlignment.ALIGN_MIDDLE);
		searchPanel.add(btnSearchEntry);
		searchPanel.setCellVerticalAlignment(btnSearchEntry, HasVerticalAlignment.ALIGN_MIDDLE);

		btnSearchEntry.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				searchEntry();
			}
		});
		
		verticalPanel.add(flexTable);
		verticalPanel.setCellHorizontalAlignment(flexTable,
				HasHorizontalAlignment.ALIGN_CENTER);
		verticalPanel.setCellVerticalAlignment(flexTable,
				HasVerticalAlignment.ALIGN_MIDDLE);

		flexTable.setWidth("");

		// FlexTable param
		flexTable.setText(0, 0, "Name");
		flexTable.setText(0, 1, "Phone Number");
		flexTable.setText(0, 2, "Remove");

		// Add styles to elements in the contact list table.
		flexTable.getRowFormatter().addStyleName(0, "contactListHeader");
		flexTable.addStyleName("contactList");
		flexTable.getCellFormatter().addStyleName(0, 0,
				"contactListDataColumns");
		flexTable.getCellFormatter().addStyleName(0, 1,
				"contactListDataColumns");
		flexTable.getCellFormatter().addStyleName(0, 2,
				"contactListRemoveColumn");
	}

	private void populateFlexTable(){

		// TODO Populate with entries from the dataStore
		if (service == null) {
			service = GWT.create(PersistentEntryService.class);
		}
		service.findAllEntries(new AsyncCallback<List<Entry>>() {
			@Override
			public void onFailure(Throwable caught) {
				System.out
						.println("PersistentService RPC call failed with findAllEntries "
								+ caught);
			}

			@Override
			public void onSuccess(List<Entry> result) {
				System.out
						.println("PersistentService RPC call succeded with findAllEntries");
				
				for (Entry e : result){
					// TODO Add the entry to the table.
					final Entry entry = e;
					int row = flexTable.getRowCount();
					entriesList.add(entry);
					flexTable.setText(row, 0, entry.getFullName());
					flexTable.setText(row, 1, entry.getPhoneNumber());
					
					// Apply style on cells
					flexTable.getCellFormatter().addStyleName(row, 0,
							"contactListDataColumns");
					flexTable.getCellFormatter().addStyleName(row, 1,
							"contactListDataColumns");
					flexTable.getCellFormatter().addStyleName(row, 2,
							"contactListRemoveColumn");
					flexTable.setCellPadding(6);

					// TODO Add a button to remove this entry from the table.
					Button btnRemoveEntry = new Button("x");
					btnRemoveEntry.addClickHandler(new ClickHandler() {
						public void onClick(ClickEvent event) {
							service.getByName(entry.getFullName(),
									new AsyncCallback<Entry>() {
										@Override
										public void onFailure(Throwable caught) {
											System.out
													.println("PersistentService RPC call failed with search for delete"
															+ caught);
										}

										@Override
										public void onSuccess(Entry result) {
											System.out.println("PersistentService RPC call succeded with search for delete");
											System.out.println("result: "+result.getFullName());
											service.deleteEntry(result,
													new AsyncCallback<Void>() {
														@Override
														public void onFailure(
																Throwable caught) {
															System.out
																	.println("PersistentService RPC call failed with deleteEntry"
																			+ caught);
														}

														@Override
														public void onSuccess(Void result) {
															System.out
																	.println("PersistentService RPC call succeded with deleteEntry");
														}
													});
										}
									});
							int removedIndex = entriesList.indexOf(entry);
							entriesList.remove(removedIndex);
							flexTable.removeRow(removedIndex + 1);
						}
					});
					flexTable.setWidget(row, 2, btnRemoveEntry);

					// Apply style on Remove Button
					btnRemoveEntry.addStyleDependentName("remove");
				}
			}
		});
	}
	
	private void addNewEntry() {
		final Entry entry = new Entry();

		String name = tFullName.getText();
		String phone = tPhoneNum.getText();
		entry.setFullName(name);
		entry.setPhoneNumber(phone);

		tFullName.setFocus(true);

		tFullName.setText("");
		tPhoneNum.setText("");

		// TODO Don't add the entry if it's already in the table.
		if (entriesList.contains(entry))
			return;

		// TODO Add the entry to the table.
		int row = flexTable.getRowCount();
		entriesList.add(entry);
		flexTable.setText(row, 0, name);
		flexTable.setText(row, 1, phone);

		// TODO Add the entry to the datasource
		if (service == null) {
			service = GWT.create(PersistentEntryService.class);
		}
		service.persistEntry(name, phone, new AsyncCallback<Void>() {
			@Override
			public void onFailure(Throwable caught) {
				System.out
						.println("PersistentService RPC call failed with persistEntry "
								+ caught);
			}

			@Override
			public void onSuccess(Void result) {
				System.out
						.println("PersistentService RPC call succeded with persistEntry");
			}
		});

		// Apply style on cells
		flexTable.getCellFormatter().addStyleName(row, 0,
				"contactListDataColumns");
		flexTable.getCellFormatter().addStyleName(row, 1,
				"contactListDataColumns");
		flexTable.getCellFormatter().addStyleName(row, 2,
				"contactListRemoveColumn");
		flexTable.setCellPadding(6);

		// TODO Add a button to remove this entry from the table.
		Button btnRemoveEntry = new Button("x");
		btnRemoveEntry.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				service.getByName(entry.getFullName(),
						new AsyncCallback<Entry>() {
							@Override
							public void onFailure(Throwable caught) {
								System.out
										.println("PersistentService RPC call failed with search for delete"
												+ caught);
							}

							@Override
							public void onSuccess(Entry result) {
								System.out.println("PersistentService RPC call succeded with search for delete");
								System.out.println("result: "+result.getFullName());
								service.deleteEntry(result,
										new AsyncCallback<Void>() {
											@Override
											public void onFailure(
													Throwable caught) {
												System.out
														.println("PersistentService RPC call failed with deleteEntry"
																+ caught);
											}

											@Override
											public void onSuccess(Void result) {
												System.out
														.println("PersistentService RPC call succeded with deleteEntry");
											}
										});
							}
						});
				int removedIndex = entriesList.indexOf(entry);
				entriesList.remove(removedIndex);
				flexTable.removeRow(removedIndex + 1);
			}
		});
		flexTable.setWidget(row, 2, btnRemoveEntry);

		// Apply style on Remove Button
		btnRemoveEntry.addStyleDependentName("remove");

	}

	private void searchEntry() {

		String name = tSearch.getText();

		if (service == null) {
			service = GWT.create(PersistentEntryService.class);
		}

		service.findByName(name, new AsyncCallback<String>() {
			@Override
			public void onFailure(Throwable caught) {
				System.out
						.println("PersistentService RPC call failed with search");
		        String details = caught.getMessage();
			}

			@Override
			public void onSuccess(String result) {
				System.out
						.println("PersistentService RPC call succeded with search");
				Window.alert(result);
				tSearch.setText("");
			}
		});

	}
}
